package com.lanhai.longheng.impl;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired; 
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.stereotype.Service;

import com.lanhai.longheng.MsgCore; 
import com.lanhai.longheng.beans.AgvBean;
import com.lanhai.longheng.beans.AgvDataBean; 
import com.lanhai.longheng.beans.DeviceBean;
import com.lanhai.longheng.beans.DotBean; 
import com.lanhai.longheng.dao.DeviceGroupDao;
import com.lanhai.longheng.dao.RoadDeviceDao;
import com.lanhai.longheng.dispatch.AgvCmdMap;
import com.lanhai.longheng.dispatch.DeviceCmdMap;
import com.lanhai.longheng.enums.AgvMountTypeEnum;  
import com.lanhai.longheng.enums.TransDirectionEnum;
import com.lanhai.longheng.interfaces.IAgv;
import com.lanhai.longheng.interfaces.IAgvEvent;
import com.lanhai.longheng.interfaces.IAgvMount;
import com.lanhai.longheng.interfaces.IDevice;
import com.lanhai.longheng.interfaces.IDot;
import com.lanhai.longheng.interfaces.IDotEvent;
import com.lanhai.longheng.interfaces.IPower;
import com.lanhai.longheng.interfaces.ITempData;
import com.lanhai.longheng.localized.LHRoadMap;
import com.lanhai.longheng.mapper.RoadMapper;
import com.lanhai.longheng.utils.Tools;

/**
 * 各点位的事件
 * 
 * @author zhengwei
 *
 */
@EnableAsync
@Service 
public class DotEventImpl implements IDotEvent {
	@Autowired
	IAgv  iAgv ;
	
	@Autowired
	IAgvMount iAgvMount;

	@Autowired
	IDevice  iDevice ;
 
	
	@Autowired
	IDot iDot;

	@Autowired
	ITempData iTempData;

	@Autowired
	IAgvEvent iAgvEvent;
	
	@Autowired
	IPower iPower;
 
 
	@Autowired
	RoadMapper roadMapper;
	
	@Autowired
	LHRoadMap lhMap;
	
	 private static final Logger agvlog =  LogManager.getLogger("agvlog");
		
	/**
	 *只处理一次
	 */
	@Override
	public void arrivedDecide(AgvBean agv, DotBean dot, AgvDataBean data) {

		if (data.getMountType() == AgvMountTypeEnum.Error) {
			// 错误的装卸状态，不处理
			MsgCore.sendMsg(agv.getAgvId(), "花篮数量异常，暂停");
			return;
		}

		// 判断对接设备分组
		if (dot.getDotNO() == 201) {
			if (data.getMountType() != AgvMountTypeEnum.AllEmpty) {
				// 有料，不能去制绒下料1
				MsgCore.sendMsg(agv.getAgvId(), "不是空车不能去制绒装花篮");
				return;
			}
			agv.setSpecialline(0);
			agv.setNextProcess("制绒下料1");
			iAgv.saveCache(agv);
		} else if (dot.getDotNO() == 260) {
			iTempData.setDotOfAgv(dot.getDotNO(), agv.getAgvId());
			// 去SE 原是209
			if (data.getMountType() == AgvMountTypeEnum.AllEmpty) {
				// 空车，去201
				// iAgvEvent.toRoad(agv, 93);

				//去215
				iAgvEvent.toRoad(agv, 119);
				return;
			} else if (data.getMountType() == AgvMountTypeEnum.UpEmptyAndDownFull) {
				// 上空下满，去SE
				agv.setNextProcess("SE1");
				iAgv.saveCache(agv);
			} else {
				// 其它状态，不动
				MsgCore.sendMsg(agv.getAgvId(), "错误的装卸状态");
				return;
			}
		} else if (dot.getDotNO() == 215) {
			/*
			// 去前氧或者返空车
			if (data.getMountType() == AgvMountTypeEnum.AllEmpty) {
				// 空车 ,去221
				// iAgvEvent.toRoad(agv, 86);
				iAgvEvent.toRoad(agv, 120);
				return;
			} else if (data.getMountType() == AgvMountTypeEnum.UpFullAndDownEmpty) {
				// 上满下空，从SE出来的（也可能是PSG出来的），去前氧
				if (agv.getNextProcess().contains("SE")) {
					agv.setNextProcess("前氧1");
					iAgv.saveCache(agv);
				} else if (agv.getNextProcess().contains("制绒上料") || agv.getNextProcess().contains("PSG")|| agv.getNextProcess().equals("")) {
					// iAgvEvent.toRoad(agv, 86);
					MsgCore.sendMsg(agv.getAgvId(), "去120" );
					iAgvEvent.toRoad(agv, 120); // 到211点
					return;
				} else if (agv.getNextProcess().contains("前氧")) { 
				} else {
					MsgCore.sendMsg(agv.getAgvId(), "错误的工序：" + agv.getNextProcess());
					return;
				}
			} else {
				// 异常
				MsgCore.sendMsg(agv.getAgvId(), "错误的装卸状态");
				return;
			}
			*/
			if (data.getMountType() == AgvMountTypeEnum.AllEmpty||data.getMountType() == AgvMountTypeEnum.UpFullAndDownEmpty) {
				// 空车 或者上满下料，从PSG出来,去221 
				iAgvEvent.toRoad(agv, 120);
				return; 
			} else {
				// 异常
				MsgCore.sendMsg(agv.getAgvId(), "错误的装卸状态");
				return;
			}
		}else if(dot.getDotNO()==268) {
			//去前氧
		     if (data.getMountType() == AgvMountTypeEnum.UpFullAndDownEmpty) {
				// 上满下空，从SE出来的（也可能是PSG出来的），去前氧
				 agv.setNextProcess("前氧1");
				 iAgv.saveCache(agv);  
			} else {
				// 异常
				MsgCore.sendMsg(agv.getAgvId(), "错误的装卸状态");
				return;
			}
		} else if (dot.getDotNO() == 226) {
			// 去制绒上(大圈，保留）
			if (data.getMountType() == AgvMountTypeEnum.AllEmpty) {
				// 空车 去235
				iAgv.saveCache(agv);
				iAgvEvent.toRoad(agv, 92);
				return;
			} else if (data.getMountType() == AgvMountTypeEnum.UpFullAndDownEmpty) {
				// 上面有料
				agv.setNextProcess("制绒上料1");
				iAgv.saveCache(agv);
			} else {
				// 异常
				MsgCore.sendMsg(agv.getAgvId(), "错误的装卸状态");
				return;
			}
		} else if (dot.getDotNO() == 265) {
			agv.setNextProcess("制绒上料1");
			iAgv.saveCache(agv);
		}
		DeviceGroupDao gbean = null;
		if (agv.getSpecialline() > 0) {
			// 定线
			gbean = iDevice.findNextDevice(agv.getAgvId(), agv.getNextProcess(), agv.getSpecialline());
		} else {
			if (dot.getDotNO() == 201 || dot.getDotNO() == 226 || dot.getDotNO() == 265) {
				// 决策点
				gbean = iDevice.findNextDeviceNospecialline(agv.getAgvId(), agv.getNextProcess());
			} else {
				// 215这种中间点,根据小车的定线来
				gbean = iDevice.findNextDevice(agv.getAgvId(), agv.getNextProcess(), agv.getSpecialline());
			}
		}
		if (gbean == null) {
			// 没有可选的机台，待命
			MsgCore.sendMsg(agv.getAgvId(),
					String.format("%s没有可用的机台，等待中", Tools.getProcess(agv.getNextProcess())));
			return;
		} else {
			RoadDeviceDao roadDao = roadMapper.getTransRoad(dot.getDotNO(), gbean.getDotno());
			if (roadDao != null && roadDao.getRoad() > 0) {
				// 把对应的设备分组锁住
				//iDevice.lockDevice(gbean.getDeviceid(), agv.getAgvId()); 
				//iDevice.unlockOtherDevice(gbean.getDeviceid(), agv.getAgvId());

				//目标机台锁住，同时其它的解锁
				iDevice.lockDeviceForTrans(gbean.getDeviceid(), agv.getAgvId());
				
				//重置机台传输数据
				DeviceCmdMap.clearState(gbean.getDeviceid());
				
				agv.setNextDeviceid(gbean.getDeviceid());
				agv.setNextRoad(roadDao.getRoad());
				agv.setNextNode(String.format("%s", roadDao.getDevicegroup()));
				iAgv.saveCache(agv);

				MsgCore.sendMsg(agv.getAgvId(),"目标机台:"+roadDao.getDevicegroup());
				
				// 分配小车路线
				iAgvEvent.toRoad(agv, roadDao.getRoad());

				// 小循环，需要记录260点的小车
				if (dot.getDotNO() == 260) {
					iTempData.setDotOfAgv(dot.getDotNO(), 0);
					lhMap.ksLeaveAgv(agv.getAgvId());
				} else if (dot.getDotNO() == 201) {
					lhMap.zrLeaveAgv(agv.getAgvId());
				}
			} else {
				// 没有路线
				agvlog.error("没有路线");
			}
		}
	}
 

	/**
	 * 充电桩
	 */
	@Override
	public void arrivedPower(AgvBean agv, DotBean dot) {
		//什么也不用做
		// iPower..lockGroup(dot.getId(), agv.getAgvId());
	}

	/**
	 * 路由点
	 */
	@Override
	public void arrivedRoute(AgvBean agv, DotBean dot) {
		if(dot.getRouteRoad()>0) {
			agv.setNextNode("行驶路线："+dot.getRouteRoad());
			iAgvEvent.toRoad(agv, dot.getRouteRoad());
		} else {
			agvlog.error("点位"+dot.getDotNO()+"没有路由路线" );
		}
	}
	
	
	

	/**
	 * 传输位
	 */
	@Override
	public void arrivedTrans(AgvBean agv, DotBean dot) {
		//记录点位信息
		iTempData.setDotOfAgv(dot.getDotNO(), agv.getAgvId()); 
		 
		//重置机台的传输状态 
		DeviceBean device=iDevice.getDaoByDot(dot.getDotNO(),true);
		if(device!=null) { 
			//清理
			DeviceCmdMap.clearState(device.getDeviceid()); 
	
			//重新锁定机台
			iDevice.lockDeviceForTrans(dot.getDotNO(), agv.getAgvId() );  
			
			//定线
			if(device.getProcess().contains("制绒下")) {
				//从制绒下料开始， agv开始定线，后续的流程以AGV的线为准。直到AGV重新回到制绒下料的机台
				agv.setSpecialline(device.getSpecialline());
			}    
			
			//清理龙恒特殊的场景
			if(device.getProcess().contains("制绒")||device.getProcess().contains("SE")) {
				  lhMap.clearAgv(agv.getAgvId());
			} 
		}
 
	}
	
 

	@Override
	public void arrivedWait(AgvBean agv, DotBean dot) {
		// 龙恒没有待命点
		
	}

	/**
	 *能进此方法肯定是传输完成
	 *  AGV的目标路线由对接机台点位设置
	 */
	@Override
	public void arrivedQR(AgvBean agv, DotBean dot) {  
    	
	   
	   //传输工位点位解锁 
	   int transdot=iDot.getTransDotNo(dot.getDotNO());
	   if(transdot>0) {
		   iTempData.setDotOfAgv(transdot, 0);  
		   // 机台解锁 。只能解自己锁定的机台
		   iDevice.unlockDeviceForDot(transdot,agv.getAgvId()); 
	   } 
	   
	   //解锁
	   if(agv.getNextDeviceid()>0) {
		   //有目标机台的，除了目标机台其它全解锁
		   iDevice.unlockOtherDevice(agv.getNextDeviceid(), agv.getAgvId());
	   }else {
		   //直接去路由点的，解锁所有
		   iDevice.unlockForAgv(agv.getAgvId());
	   }
	 
	   //小车传输锁
	   AgvCmdMap.setTransing(agv.getAgvId(), false);
	   
	   //小车传输完成状态
	   agv.setFinishTrans(false); 
		agv.setUpHasTrans(false);
		agv.setDownHasTrans(false);
	   iAgv.saveCache(agv);
		
	  
	   
	   
	   //二维码指定的路由优先处理 
	   
	   //不需要锁机台，在选择目标机台时，已经上锁了
	   if(agv.getNextRoad()>0) {
		   int rroud=agv.getNextRoad(); 
		   //小车跑路
		   iAgvEvent.toRoad(agv, rroud); 
		   return; 
	   } else {
		   MsgCore.sendMsg(agv.getAgvId(), "数据错误，缺少目标路线");
		   System.out.println("wtf");
	   }
	 
	}
	 

	/**
	 * 计料规则 
	 * @param process
	 * @return
	 */
	TransDirectionEnum getGroupTrans(String process) {
		TransDirectionEnum re=TransDirectionEnum.Both;
		if(process.startsWith("制绒下料"))
		{
			re=TransDirectionEnum.OnlyOut;
		}else if(process.startsWith("扩散")) {
			re=TransDirectionEnum.OnlyIn;
		}
		return re;
	}
	
	
	
	
	/**
	 * 到达普通点位
	 */
	@Override
	public void arrivedNormal(AgvBean agv, DotBean dot) {
		int dotno=dot.getDotNO();
		if(dotno==261) {
			//判断路1是否被另一方向占有，260是否有车 ，如果可以，走110
			if(lhMap.ksCanRight(agv.getAgvId())&&iTempData.getAgvIdByDotNo(260)==0) {
				lhMap.ksEnterAgv( false,agv.getAgvId());
				iAgvEvent.toRoad(agv, 110);
			}else {
				MsgCore.sendMsg(agv.getAgvId(), "等待前方放行，或分配SE的机台");
			}
		}else if(dotno==211) {
			//路1如果没有同向占用，去209（走121）
			if(lhMap.ksCanLeft(agv.getAgvId())) {
				lhMap.ksEnterAgv(true,agv.getAgvId());
				iAgvEvent.toRoad(agv, 121);
			}else {
				MsgCore.sendMsg(agv.getAgvId(), "等待前方放行");
			}
		}else if(dotno==209) {
			//路2如果没有同向占用，去264(走122）
			if(lhMap.zrCanLeft(agv.getAgvId())) {
				lhMap.zrEnterAgv(true,agv.getAgvId());
				iAgvEvent.toRoad(agv, 122);
				
				//解锁路1
				lhMap.ksLeaveAgv(agv.getAgvId()); 
			}else {
				MsgCore.sendMsg(agv.getAgvId(), "等待前方放行"); 
			}
		}else if(dotno==264) {
			//解锁路2，走125线
			lhMap.zrLeaveAgv(agv.getAgvId());
			iAgvEvent.toRoad(agv, 125);
		}else if(dotno==243) { 
			//路2如果没有锁，去201 （走136）
			if(lhMap.zrCanRight(agv.getAgvId())) {
				lhMap.zrEnterAgv(false,agv.getAgvId());
				iAgvEvent.toRoad(agv, 136);  
			}else {
				MsgCore.sendMsg(agv.getAgvId(), "等待前方放行"); 
				System.out.println(agv.getAgvId()+"等待前方放行" );
			}
			
		}else {
			MsgCore.sendMsg(agv.getAgvId(), "当前点位没有目标路线");
			agvlog.error("点位"+dot.getDotNO()+"没有目标路线" );
		}
	}


	@Override
	public void arrivedPowerCheck(AgvBean agv, AgvDataBean data, DotBean dot) {
		if(data.getPower()<=70 ) {
			//电量低于60并且充电通道没有被锁去充电桩
			int pre=iPower.agvToPower(dot.getDotNO(), agv);
			if(pre==1) {
				//去充电桩成功，就不需要后面的操作了
				return;
			} else {
				if(data.getPower()<=60) {
					MsgCore.sendMsg(agv.getAgvId(), "AGV电量不足，无法保证跑完一条生产线");
					return  ;
				}else {
					//60-70之间，还能跑一会儿 
				} 
			} 
		} 
		if(dot.getRouteRoad()>0) {
		    MsgCore.sendMsg(agv.getAgvId(),  "行驶路线："+dot.getRouteRoad());
			iAgvEvent.toRoad(agv, dot.getRouteRoad());
		}else { 
			 MsgCore.sendMsg(agv.getAgvId(),  "点位"+dot.getDotNO()+"没有路由路线_powercheck");
			agvlog.error("点位"+dot.getDotNO()+"没有路由路线_powercheck" );
		}
		
	}
 

}
